1use crate::ext::atomic::*;
3use crate::ext::io::*;
4use crate::scripts::base::*;
5use crate::types::*;
6use crate::utils::bit_stream::*;
7use crate::utils::img::*;
8use crate::utils::struct_pack::*;
9use crate::utils::threadpool::*;
10use anyhow::Result;
11use msg_tool_macro::*;
12use std::io::{Read, Seek, Write};
13use std::sync::atomic::AtomicBool;
14use std::sync::{Arc, Mutex};
15
16#[derive(Debug)]
17pub struct BgiCBGBuilder {}
19
20impl BgiCBGBuilder {
21 pub const fn new() -> Self {
23 BgiCBGBuilder {}
24 }
25}
26
27impl ScriptBuilder for BgiCBGBuilder {
28 fn default_encoding(&self) -> Encoding {
29 Encoding::Cp932
30 }
31
32 fn build_script(
33 &self,
34 data: Vec<u8>,
35 _filename: &str,
36 _encoding: Encoding,
37 _archive_encoding: Encoding,
38 config: &ExtraConfig,
39 _archive: Option<&Box<dyn Script>>,
40 ) -> Result<Box<dyn Script>> {
41 Ok(Box::new(BgiCBG::new(data, config)?))
42 }
43
44 fn extensions(&self) -> &'static [&'static str] {
45 &[]
46 }
47
48 fn script_type(&self) -> &'static ScriptType {
49 &ScriptType::BGICbg
50 }
51
52 fn is_image(&self) -> bool {
53 true
54 }
55
56 fn is_this_format(&self, _filename: &str, buf: &[u8], buf_len: usize) -> Option<u8> {
57 if buf_len >= 0x10 && buf.starts_with(b"CompressedBG___") {
58 return Some(255);
59 }
60 None
61 }
62
63 fn can_create_image_file(&self) -> bool {
64 true
65 }
66
67 fn create_image_file<'a>(
68 &'a self,
69 data: ImageData,
70 mut writer: Box<dyn WriteSeek + 'a>,
71 _options: &ExtraConfig,
72 ) -> Result<()> {
73 let encoder = CbgEncoder::new(data)?;
74 let data = encoder.encode()?;
75 writer.write_all(&data)?;
76 Ok(())
77 }
78}
79
80#[derive(Debug, StructPack, StructUnpack)]
81struct BgiCBGHeader {
82 width: u16,
83 height: u16,
84 bpp: u32,
85 _unk: u64,
86 intermediate_length: u32,
87 key: u32,
88 enc_length: u32,
89 check_sum: u8,
90 check_xor: u8,
91 version: u16,
92}
93
94#[derive(Debug, Clone, Copy, PartialEq, Eq)]
95enum CbgColorType {
96 Bgra32,
97 Bgr24,
98 Grayscale,
99 Bgr565,
100}
101
102fn convert_bgr565_to_bgr24(input: Vec<u8>, width: u16, height: u16) -> ImageData {
103 let pixel_count = width as usize * height as usize;
104 let mut output = Vec::with_capacity(pixel_count * 3);
105
106 for chunk in input.chunks_exact(2) {
107 let pixel = u16::from_le_bytes([chunk[0], chunk[1]]);
108
109 let blue_5bit = (pixel & 0x1) as u8;
110 let green_6bit = ((pixel >> 5) & 0x3) as u8;
111 let red_5bit = ((pixel >> 11) & 0x1) as u8;
112
113 let blue = ((blue_5bit as u16 * 255) / 31) as u8;
114 let green = ((green_6bit as u16 * 255) / 63) as u8;
115 let red = ((red_5bit as u16 * 255) / 31) as u8;
116
117 output.push(blue);
118 output.push(green);
119 output.push(red);
120 }
121
122 ImageData {
123 width: width as u32,
124 height: height as u32,
125 color_type: ImageColorType::Bgr,
126 depth: 8,
127 data: output,
128 }
129}
130
131#[derive(Debug)]
132pub struct BgiCBG {
134 header: BgiCBGHeader,
135 data: MemReader,
136 color_type: CbgColorType,
137 decode_workers: usize,
138}
139
140impl BgiCBG {
141 pub fn new(data: Vec<u8>, config: &ExtraConfig) -> Result<Self> {
146 let mut reader = MemReader::new(data);
147 let mut magic = [0u8; 16];
148 reader.read_exact(&mut magic)?;
149 if !magic.starts_with(b"CompressedBG___") {
150 return Err(anyhow::anyhow!("Invalid magic: {:?}", magic));
151 }
152 let header = BgiCBGHeader::unpack(&mut reader, false, Encoding::Cp932)?;
153 if header.version > 2 {
154 return Err(anyhow::anyhow!("Unsupported version: {}", header.version));
155 }
156 let color_type = match header.bpp {
157 32 => CbgColorType::Bgra32,
158 24 => CbgColorType::Bgr24,
159 8 => CbgColorType::Grayscale,
160 16 => {
161 if header.version == 2 {
162 return Err(anyhow::anyhow!("Unsupported BPP 16 in version 2"));
163 }
164 CbgColorType::Bgr565
165 }
166 _ => return Err(anyhow::anyhow!("Unsupported BPP: {}", header.bpp)),
167 };
168 Ok(BgiCBG {
169 header,
170 data: reader,
171 color_type,
172 decode_workers: config.bgi_img_workers.max(1),
173 })
174 }
175}
176
177impl Script for BgiCBG {
178 fn default_output_script_type(&self) -> OutputScriptType {
179 OutputScriptType::Json
180 }
181
182 fn default_format_type(&self) -> FormatOptions {
183 FormatOptions::None
184 }
185
186 fn is_image(&self) -> bool {
187 true
188 }
189
190 fn export_image(&self) -> Result<ImageData> {
191 let decoder = CbgDecoder::new(
192 self.data.to_ref(),
193 &self.header,
194 self.color_type,
195 self.decode_workers,
196 )?;
197 Ok(decoder.unpack()?)
198 }
199
200 fn import_image<'a>(
201 &'a self,
202 data: ImageData,
203 mut file: Box<dyn WriteSeek + 'a>,
204 ) -> Result<()> {
205 let encoder = CbgEncoder::new(data)?;
206 let encoded_data = encoder.encode()?;
207 file.write_all(&encoded_data)?;
208 Ok(())
209 }
210}
211
212struct CbgDecoder<'a> {
213 stream: MsbBitStream<MemReaderRef<'a>>,
214 info: &'a BgiCBGHeader,
215 color_type: CbgColorType,
216 key: u32,
217 magic: u32,
218 pixel_size: u8,
219 stride: usize,
220 workers: usize,
221}
222
223impl<'a> CbgDecoder<'a> {
224 fn new(
225 reader: MemReaderRef<'a>,
226 info: &'a BgiCBGHeader,
227 color_type: CbgColorType,
228 workers: usize,
229 ) -> Result<Self> {
230 let magic = 0;
231 let key = info.key;
232 let stream = MsbBitStream::new(reader);
233 let pixel_size = info.bpp as u8 / 8;
234 let stride = info.width as usize * (info.bpp as usize / 8);
235 Ok(CbgDecoder {
236 stream,
237 info,
238 key,
239 magic,
240 color_type,
241 pixel_size,
242 stride,
243 workers,
244 })
245 }
246
247 fn unpack(mut self) -> Result<ImageData> {
248 self.stream.m_input.pos = 0x30;
249 if self.info.version < 2 {
250 return self.unpack_v1();
251 } else if self.info.version == 2 {
252 if self.info.enc_length < 0x80 {
253 return Err(anyhow::anyhow!(
254 "Invalid encoded length: {}",
255 self.info.enc_length
256 ));
257 }
258 return self.unpack_v2();
259 }
260 Err(anyhow::anyhow!("Unknown version: {}", self.info.version))
261 }
262
263 fn unpack_v1(&mut self) -> Result<ImageData> {
264 let leaf_nodes_weight = {
265 let stream = MemReader::new(self.read_encoded()?);
266 let mut stream_ref = stream.to_ref();
267 Self::read_weight_table(&mut stream_ref, 0x100)?
268 };
269 let tree = HuffmanTree::new(&leaf_nodes_weight, false);
270 let mut packed = Vec::with_capacity(self.info.intermediate_length as usize);
271 packed.resize(self.info.intermediate_length as usize, 0);
272 self.huffman_decompress(&tree, &mut packed)?;
273 let buf_size = self.stride * self.info.height as usize;
274 let mut output = Vec::with_capacity(buf_size);
275 output.resize(buf_size, 0);
276 Self::unpack_zeros(&packed, &mut output);
277 self.reverse_average_sampling(&mut output);
278 let color_type = match self.color_type {
279 CbgColorType::Bgra32 => ImageColorType::Bgra,
280 CbgColorType::Bgr24 => ImageColorType::Bgr,
281 CbgColorType::Grayscale => ImageColorType::Grayscale,
282 CbgColorType::Bgr565 => {
283 return Ok(convert_bgr565_to_bgr24(
284 output,
285 self.info.width,
286 self.info.height,
287 ));
288 }
289 };
290 Ok(ImageData {
291 width: self.info.width as u32,
292 height: self.info.height as u32,
293 color_type,
294 depth: 8,
295 data: output,
296 })
297 }
298
299 fn unpack_v2(&mut self) -> Result<ImageData> {
300 let dct_data = self.read_encoded()?;
301 let mut dct = [[0.0f32; 64]; 2];
302 for i in 0..0x80 {
303 dct[i >> 6][i & 0x3f] = dct_data[i] as f32 * DCT_TABLE[i & 0x3f];
304 }
305
306 let base_offset = self.stream.m_input.pos;
307 let tree1 = HuffmanTree::new(
308 &Self::read_weight_table(&mut self.stream.m_input, 0x10)?,
309 true,
310 );
311 let tree2 = HuffmanTree::new(
312 &Self::read_weight_table(&mut self.stream.m_input, 0xB0)?,
313 true,
314 );
315
316 let width = ((self.info.width as i32 + 7) & -8) as i32;
317 let height = ((self.info.height as i32 + 7) & -8) as i32;
318 let y_blocks = height / 8;
319
320 let mut offsets = Vec::with_capacity((y_blocks + 1) as usize);
321 let input_base =
322 (self.stream.m_input.pos + ((y_blocks + 1) as usize * 4) - base_offset) as i32;
323
324 for _ in 0..=y_blocks {
325 let offset = self.stream.m_input.read_i32()?;
326 offsets.push(offset - input_base);
327 }
328
329 let input = self.stream.m_input.data[self.stream.m_input.pos..].to_vec();
330 let pad_skip = ((width >> 3) + 7) >> 3;
331
332 let output_size = (width * height * 4) as usize;
333 let output = vec![0u8; output_size];
334 let output_mutex = Mutex::new(output);
335
336 let decoder = Arc::new(ParallelCbgDecoder {
337 input,
338 output: output_mutex,
339 bpp: self.info.bpp as i32,
340 width,
341 height,
342 tree1,
343 tree2,
344 dct,
345 has_alpha: AtomicBool::new(false),
346 });
347
348 let thread_pool = ThreadPool::new(self.workers, Some("cbg-decoder-worker-"), false)?;
349 let mut dst = 0i32;
350
351 for i in 0..y_blocks {
352 let block_offset = offsets[i as usize] + pad_skip;
353 let next_offset = if i + 1 == y_blocks {
354 decoder.input.len() as i32
355 } else {
356 offsets[(i + 1) as usize]
357 };
358 let closure_dst = dst;
359 let decoder_ref = Arc::clone(&decoder);
360
361 thread_pool.execute(
362 move |_| {
363 decoder_ref.unpack_block(block_offset, next_offset - block_offset, closure_dst)
364 },
365 true,
366 )?;
367 dst += width * 32;
368 }
369
370 if self.info.bpp == 32 {
371 let decoder_ref = Arc::clone(&decoder);
372 thread_pool.execute(
373 move |_| decoder_ref.unpack_alpha(offsets[y_blocks as usize]),
374 true,
375 )?;
376 }
377
378 let tasks = thread_pool.into_results();
379
380 for task in tasks {
381 task?;
382 }
383
384 let has_alpha = decoder.has_alpha.qload();
385 let mut output = decoder
386 .output
387 .lock()
388 .map_err(|e| anyhow::anyhow!("Failed to lock output: {}", e))?
389 .clone();
390
391 if !has_alpha {
392 let mut src_idx = 0;
393 let mut dst_idx = 0;
394 for _ in 0..self.info.height {
395 for _ in 0..self.info.width {
396 output[dst_idx] = output[src_idx];
397 output[dst_idx + 1] = output[src_idx + 1];
398 output[dst_idx + 2] = output[src_idx + 2];
399 src_idx += 4;
400 dst_idx += 3;
401 }
402 }
403 output.truncate(dst_idx);
404 }
405
406 let color_type = if has_alpha {
407 ImageColorType::Bgra
408 } else {
409 ImageColorType::Bgr
410 };
411
412 let img = ImageData {
413 width: decoder.width as u32,
414 height: decoder.height as u32,
415 color_type,
416 depth: 8,
417 data: output,
418 };
419
420 if decoder.width != self.info.width as i32 || decoder.height != self.info.height as i32 {
421 return Ok(draw_on_canvas(
422 img,
423 self.info.width as u32,
424 self.info.height as u32,
425 0,
426 0,
427 )?);
428 }
429
430 Ok(img)
431 }
432
433 fn read_encoded(&mut self) -> Result<Vec<u8>> {
434 let mut output = Vec::with_capacity(self.info.enc_length as usize);
435 output.resize(self.info.enc_length as usize, 0);
436 self.stream.m_input.read_exact(&mut output)?;
437 let mut sum = 0u8;
438 let mut xor = 0u8;
439 for i in 0..output.len() {
440 output[i] = output[i].wrapping_sub(self.update_key());
441 sum = sum.wrapping_add(output[i]);
442 xor ^= output[i];
443 }
444 if sum != self.info.check_sum || xor != self.info.check_xor {
445 return Err(anyhow::anyhow!(
446 "Checksum mismatch: sum={}, xor={}",
447 sum,
448 xor
449 ));
450 }
451 Ok(output)
452 }
453
454 fn read_int(input: &mut MemReaderRef<'_>) -> Result<i32> {
455 let mut v = 0;
456 let mut code_length = 0;
457 loop {
458 let code = input.read_i8()?;
459 if code_length >= 32 {
460 return Err(anyhow::anyhow!(
461 "Failed to raed int: code={}, code_length={}",
462 code,
463 code_length
464 ));
465 }
466 v |= ((code & 0x7f) as i32) << code_length;
467 code_length += 7;
468 if code & -128 == 0 {
469 break;
470 }
471 }
472 Ok(v)
473 }
474
475 fn read_weight_table(input: &mut MemReaderRef<'_>, length: usize) -> Result<Vec<u32>> {
476 let mut weights = Vec::with_capacity(length);
477 for _ in 0..length {
478 let weight = Self::read_int(input)? as u32;
479 weights.push(weight);
480 }
481 Ok(weights)
482 }
483
484 fn huffman_decompress(&mut self, tree: &HuffmanTree, output: &mut [u8]) -> Result<()> {
485 for dst in 0..output.len() {
486 output[dst] = tree.decode_token(&mut self.stream)? as u8;
487 }
488 Ok(())
489 }
490
491 fn unpack_zeros(input: &[u8], output: &mut [u8]) {
492 let mut dst = 0;
493 let mut dec_zero = 0;
494 let mut src = 0;
495 while dst < output.len() {
496 let mut code_length = 0;
497 let mut count = 0;
498 let mut code;
499 loop {
500 if src >= input.len() {
501 return;
502 }
503 code = input[src];
504 src += 1;
505 count |= ((code & 0x7f) as usize) << code_length;
506 code_length += 7;
507 if code & 0x80 == 0 {
508 break;
509 }
510 }
511 if dst + count > output.len() {
512 break;
513 }
514 if dec_zero == 0 {
515 if src + count > input.len() {
516 break;
517 }
518 output[dst..dst + count].copy_from_slice(&input[src..src + count]);
519 src += count;
520 } else {
521 for i in 0..count {
522 output[dst + i] = 0;
523 }
524 }
525 dec_zero ^= 1;
526 dst += count;
527 }
528 }
529
530 fn reverse_average_sampling(&self, output: &mut [u8]) {
531 for y in 0..self.info.height {
532 let line = y as usize * self.stride;
533 for x in 0..self.info.width {
534 let pixel = line + x as usize * self.pixel_size as usize;
535 for p in 0..self.pixel_size {
536 let mut avg = 0u32;
537 if x > 0 {
538 avg = avg.wrapping_add(
539 output[pixel + p as usize - self.pixel_size as usize] as u32,
540 );
541 }
542 if y > 0 {
543 avg = avg.wrapping_add(output[pixel + p as usize - self.stride] as u32);
544 }
545 if x > 0 && y > 0 {
546 avg /= 2;
547 }
548 if avg != 0 {
549 output[pixel + p as usize] =
550 output[pixel + p as usize].wrapping_add(avg as u8);
551 }
552 }
553 }
554 }
555 }
556
557 fn update_key(&mut self) -> u8 {
558 let v0 = 20021 * (self.key & 0xffff);
559 let mut v1 = self.magic | (self.key >> 16);
560 v1 = v1
561 .overflowing_mul(20021)
562 .0
563 .overflowing_add(self.key.overflowing_mul(346).0)
564 .0;
565 v1 = (v1 + (v0 >> 16)) & 0xffff;
566 self.key = (v1 << 16) + (v0 & 0xffff) + 1;
567 v1 as u8
568 }
569}
570
571#[derive(Debug)]
572struct HuffmanNode {
573 valid: bool,
574 is_parent: bool,
575 weight: u32,
576 left_index: usize,
577 right_index: usize,
578}
579
580#[derive(Debug)]
581struct HuffmanTree {
582 nodes: Vec<HuffmanNode>,
583}
584
585impl HuffmanTree {
586 fn new(weights: &[u32], v2: bool) -> Self {
587 let mut nodes = Vec::with_capacity(weights.len() * 2);
588 let mut root_node_weight = 0u32;
589 for weight in weights {
590 let node = HuffmanNode {
591 valid: *weight != 0,
592 is_parent: false,
593 weight: *weight,
594 left_index: 0,
595 right_index: 0,
596 };
597 nodes.push(node);
598 root_node_weight = root_node_weight.wrapping_add(*weight);
599 }
600 let mut child_node_index = [0usize; 2];
601 loop {
602 let mut weight = 0u32;
603 for i in 0usize..2usize {
604 let mut min_weight = u32::MAX;
605 child_node_index[i] = usize::MAX;
606 let mut n = 0;
607 if v2 {
608 while n < nodes.len() {
609 if nodes[n].valid {
610 min_weight = nodes[n].weight;
611 child_node_index[i] = n;
612 n += 1;
613 break;
614 }
615 n += 1;
616 }
617 n = n.max(i + 1);
618 }
619 while n < nodes.len() {
620 if nodes[n].valid && nodes[n].weight < min_weight {
621 min_weight = nodes[n].weight;
622 child_node_index[i] = n;
623 }
624 n += 1;
625 }
626 if child_node_index[i] == usize::MAX {
627 continue;
628 }
629 nodes[child_node_index[i]].valid = false;
630 weight = weight.wrapping_add(nodes[child_node_index[i]].weight);
631 }
632 let parent_node = HuffmanNode {
633 valid: true,
634 is_parent: true,
635 left_index: child_node_index[0],
636 right_index: child_node_index[1],
637 weight,
638 };
639 nodes.push(parent_node);
640 if weight >= root_node_weight {
641 break;
642 }
643 }
644 Self { nodes }
645 }
646
647 fn decode_token(&self, stream: &mut MsbBitStream<MemReaderRef<'_>>) -> Result<usize> {
648 let mut node_index = self.nodes.len() - 1;
649 loop {
650 let bit = stream.get_next_bit()?;
651 if !bit {
652 node_index = self.nodes[node_index].left_index;
653 } else {
654 node_index = self.nodes[node_index].right_index;
655 }
656 if !self.nodes[node_index].is_parent {
657 return Ok(node_index);
658 }
659 }
660 }
661
662 fn encode_token(&self, stream: &mut MsbBitWriter<impl Write>, token: usize) -> Result<()> {
663 let mut path = Vec::new();
664 if !self.find_path(self.nodes.len() - 1, token, &mut path) {
665 return Err(anyhow::anyhow!("Token not found in Huffman tree"));
666 }
667 for &bit in path.iter().rev() {
668 stream.put_bit(bit)?;
669 }
670 Ok(())
671 }
672
673 fn find_path(&self, node_index: usize, token: usize, path: &mut Vec<bool>) -> bool {
674 if node_index == usize::MAX {
675 return false;
676 }
677 let node = &self.nodes[node_index];
678 if !node.is_parent {
679 return node_index == token;
680 }
681
682 if self.find_path(node.left_index, token, path) {
683 path.push(false);
684 return true;
685 }
686 if self.find_path(node.right_index, token, path) {
687 path.push(true);
688 return true;
689 }
690 false
691 }
692}
693
694const DCT_TABLE: [f32; 64] = [
695 1.00000000, 1.38703990, 1.30656302, 1.17587554, 1.00000000, 0.78569496, 0.54119611, 0.27589938,
696 1.38703990, 1.92387950, 1.81225491, 1.63098633, 1.38703990, 1.08979023, 0.75066054, 0.38268343,
697 1.30656302, 1.81225491, 1.70710683, 1.53635550, 1.30656302, 1.02655995, 0.70710677, 0.36047992,
698 1.17587554, 1.63098633, 1.53635550, 1.38268340, 1.17587554, 0.92387950, 0.63637930, 0.32442334,
699 1.00000000, 1.38703990, 1.30656302, 1.17587554, 1.00000000, 0.78569496, 0.54119611, 0.27589938,
700 0.78569496, 1.08979023, 1.02655995, 0.92387950, 0.78569496, 0.61731654, 0.42521504, 0.21677275,
701 0.54119611, 0.75066054, 0.70710677, 0.63637930, 0.54119611, 0.42521504, 0.29289323, 0.14931567,
702 0.27589938, 0.38268343, 0.36047992, 0.32442334, 0.27589938, 0.21677275, 0.14931567, 0.07612047,
703];
704
705const BLOCK_FILL_ORDER: [u8; 64] = [
706 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20,
707 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59,
708 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63,
709];
710
711struct ParallelCbgDecoder {
712 input: Vec<u8>,
713 output: Mutex<Vec<u8>>,
714 bpp: i32,
715 width: i32,
716 height: i32,
717 tree1: HuffmanTree,
718 tree2: HuffmanTree,
719 dct: [[f32; 64]; 2],
720 has_alpha: AtomicBool,
721}
722
723impl ParallelCbgDecoder {
724 fn unpack_block(&self, offset: i32, length: i32, dst: i32) -> Result<()> {
725 let input = MemReaderRef::new(&self.input[offset as usize..(offset + length) as usize]);
726 let mut reader = MsbBitStream::new(input);
727
728 let block_size = CbgDecoder::read_int(&mut reader.m_input)?;
729 if block_size == -1 {
730 return Ok(());
731 }
732
733 let mut color_data = vec![0i16; block_size as usize];
734 let mut acc = 0i32;
735 let mut i = 0i32;
736
737 while i < block_size && reader.m_input.pos < reader.m_input.data.len() {
738 let count = self.tree1.decode_token(&mut reader)?;
739 if count != 0 {
740 let mut v = reader.get_bits(count as u32)? as i32;
741 if (v >> (count - 1)) == 0 {
742 v = (-1 << count | v) + 1;
743 }
744 acc += v;
745 }
746 color_data[i as usize] = acc as i16;
747 i += 64;
748 }
749
750 if (reader.m_cached_bits & 7) != 0 {
751 reader.get_bits(reader.m_cached_bits & 7)?;
752 }
753
754 i = 0;
755 while i < block_size && reader.m_input.pos < reader.m_input.data.len() {
756 let mut index = 1usize;
757 while index < 64 && reader.m_input.pos < reader.m_input.data.len() {
758 let code = self.tree2.decode_token(&mut reader)?;
759 if code == 0 {
760 break;
761 }
762 if code == 0xf {
763 index += 0x10;
764 continue;
765 }
766 index += code & 0xf;
767 if index >= BLOCK_FILL_ORDER.len() {
768 break;
769 }
770 let bits = code >> 4;
771 let mut v = reader.get_bits(bits as u32)? as i32;
772 if bits != 0 && (v >> (bits - 1)) == 0 {
773 v = (-1 << bits | v) + 1;
774 }
775 color_data[i as usize + BLOCK_FILL_ORDER[index] as usize] = v as i16;
776 index += 1;
777 }
778 i += 64;
779 }
780
781 if self.bpp == 8 {
782 self.decode_grayscale(&color_data, dst)?;
783 } else {
784 self.decode_rgb(&color_data, dst)?;
785 }
786
787 Ok(())
788 }
789
790 fn decode_rgb(&self, data: &[i16], dst: i32) -> Result<()> {
791 let block_count = self.width / 8;
792 let mut dst = dst as usize;
793
794 for i in 0..block_count {
795 let mut src = (i * 64) as usize;
796 let mut ycbcr_block = [[0i16; 3]; 64];
797
798 for channel in 0..3 {
799 self.decode_dct(channel, data, src, &mut ycbcr_block)?;
800 src += (self.width * 8) as usize;
801 }
802
803 let mut output = self
804 .output
805 .lock()
806 .map_err(|e| anyhow::anyhow!("Failed to lock output: {}", e))?;
807
808 for j in 0..64 {
809 let cy = ycbcr_block[j][0] as f32;
810 let cb = ycbcr_block[j][1] as f32;
811 let cr = ycbcr_block[j][2] as f32;
812
813 let r = cy + 1.402f32 * cr - 178.956f32;
815 let g = cy - 0.34414f32 * cb - 0.71414f32 * cr + 135.95984f32;
816 let b = cy + 1.772f32 * cb - 226.316f32;
817
818 let y = j >> 3;
819 let x = j & 7;
820 let p = (y * self.width as usize + x) * 4 + dst;
821
822 output[p] = Self::float_to_byte(b);
823 output[p + 1] = Self::float_to_byte(g);
824 output[p + 2] = Self::float_to_byte(r);
825 }
826 dst += 32;
827 }
828 Ok(())
829 }
830
831 fn decode_grayscale(&self, data: &[i16], dst: i32) -> Result<()> {
832 let mut src = 0;
833 let block_count = self.width / 8;
834 let mut dst = dst as usize;
835
836 for _ in 0..block_count {
837 let mut ycbcr_block = [[0i16; 3]; 64];
838 self.decode_dct(0, data, src, &mut ycbcr_block)?;
839 src += 64;
840
841 let mut output = self
842 .output
843 .lock()
844 .map_err(|e| anyhow::anyhow!("Failed to lock output: {}", e))?;
845
846 for j in 0..64 {
847 let y = j >> 3;
848 let x = j & 7;
849 let p = (y * self.width as usize + x) * 4 + dst;
850 let value = ycbcr_block[j][0] as u8;
851
852 output[p] = value;
853 output[p + 1] = value;
854 output[p + 2] = value;
855 }
856 dst += 32;
857 }
858 Ok(())
859 }
860
861 fn unpack_alpha(&self, offset: i32) -> Result<()> {
862 let mut input = MemReaderRef::new(&self.input[offset as usize..]);
863
864 if input.read_i32()? != 1 {
865 return Ok(());
866 }
867
868 let mut dst = 3;
869 let mut ctl = 1i32 << 1;
870
871 let mut output = self
872 .output
873 .lock()
874 .map_err(|e| anyhow::anyhow!("Failed to lock output: {}", e))?;
875
876 while dst < output.len() {
877 ctl >>= 1;
878 if ctl == 1 {
879 ctl = (input.read_u8()? as i32) | 0x100;
880 }
881
882 if (ctl & 1) != 0 {
883 let v = input.read_u16()? as i32;
884 let mut x = v & 0x3f;
885 if x > 0x1f {
886 x |= -0x40;
887 }
888 let mut y = (v >> 6) & 7;
889 if y != 0 {
890 y |= -8;
891 }
892 let count = ((v >> 9) & 0x7f) + 3;
893
894 let src = dst as isize + (x as isize + y as isize * self.width as isize) * 4;
895 if src < 0 || src >= dst as isize {
896 return Ok(());
897 }
898
899 let mut src = src as usize;
900 for _ in 0..count {
901 output[dst] = output[src];
902 src += 4;
903 dst += 4;
904 }
905 } else {
906 output[dst] = input.read_u8()?;
907 dst += 4;
908 }
909 }
910
911 self.has_alpha.qsave(true);
912 Ok(())
913 }
914
915 fn decode_dct(
916 &self,
917 channel: usize,
918 data: &[i16],
919 src: usize,
920 output: &mut [[i16; 3]; 64],
921 ) -> Result<()> {
922 let d = if channel > 0 { 1 } else { 0 };
923 let mut tmp = [[0f32; 8]; 8];
924
925 for i in 0..8 {
926 if data[src + 8 + i] == 0
928 && data[src + 16 + i] == 0
929 && data[src + 24 + i] == 0
930 && data[src + 32 + i] == 0
931 && data[src + 40 + i] == 0
932 && data[src + 48 + i] == 0
933 && data[src + 56 + i] == 0
934 {
935 let t = data[src + i] as f32 * self.dct[d][i];
936 for row in 0..8 {
937 tmp[row][i] = t;
938 }
939 continue;
940 }
941
942 let v1 = data[src + i] as f32 * self.dct[d][i];
943 let v2 = data[src + 8 + i] as f32 * self.dct[d][8 + i];
944 let v3 = data[src + 16 + i] as f32 * self.dct[d][16 + i];
945 let v4 = data[src + 24 + i] as f32 * self.dct[d][24 + i];
946 let v5 = data[src + 32 + i] as f32 * self.dct[d][32 + i];
947 let v6 = data[src + 40 + i] as f32 * self.dct[d][40 + i];
948 let v7 = data[src + 48 + i] as f32 * self.dct[d][48 + i];
949 let v8 = data[src + 56 + i] as f32 * self.dct[d][56 + i];
950
951 let v10 = v1 + v5;
952 let v11 = v1 - v5;
953 let v12 = v3 + v7;
954 let v13 = (v3 - v7) * 1.414213562f32 - v12;
955 let v1 = v10 + v12;
956 let v7 = v10 - v12;
957 let v3 = v11 + v13;
958 let v5 = v11 - v13;
959 let v14 = v2 + v8;
960 let v15 = v2 - v8;
961 let v16 = v6 + v4;
962 let v17 = v6 - v4;
963 let v8 = v14 + v16;
964 let v11 = (v14 - v16) * 1.414213562f32;
965 let v9 = (v17 + v15) * 1.847759065f32;
966 let v10 = 1.082392200f32 * v15 - v9;
967 let v13 = -2.613125930f32 * v17 + v9;
968 let v6 = v13 - v8;
969 let v4 = v11 - v6;
970 let v2 = v10 + v4;
971
972 tmp[0][i] = v1 + v8;
973 tmp[1][i] = v3 + v6;
974 tmp[2][i] = v5 + v4;
975 tmp[3][i] = v7 - v2;
976 tmp[4][i] = v7 + v2;
977 tmp[5][i] = v5 - v4;
978 tmp[6][i] = v3 - v6;
979 tmp[7][i] = v1 - v8;
980 }
981
982 let mut dst = 0;
983 for i in 0..8 {
984 let v10 = tmp[i][0] + tmp[i][4];
985 let v11 = tmp[i][0] - tmp[i][4];
986 let v12 = tmp[i][2] + tmp[i][6];
987 let v13 = tmp[i][2] - tmp[i][6];
988 let v14 = tmp[i][1] + tmp[i][7];
989 let v15 = tmp[i][1] - tmp[i][7];
990 let v16 = tmp[i][5] + tmp[i][3];
991 let v17 = tmp[i][5] - tmp[i][3];
992
993 let v13 = 1.414213562f32 * v13 - v12;
994 let v1 = v10 + v12;
995 let v7 = v10 - v12;
996 let v3 = v11 + v13;
997 let v5 = v11 - v13;
998 let v8 = v14 + v16;
999 let v11 = (v14 - v16) * 1.414213562f32;
1000 let v9 = (v17 + v15) * 1.847759065f32;
1001 let v10 = v9 - v15 * 1.082392200f32;
1002 let v13 = v9 - v17 * 2.613125930f32;
1003 let v6 = v13 - v8;
1004 let v4 = v11 - v6;
1005 let v2 = v10 - v4;
1006
1007 output[dst][channel] = Self::float_to_short(v1 + v8);
1008 output[dst + 1][channel] = Self::float_to_short(v3 + v6);
1009 output[dst + 2][channel] = Self::float_to_short(v5 + v4);
1010 output[dst + 3][channel] = Self::float_to_short(v7 + v2);
1011 output[dst + 4][channel] = Self::float_to_short(v7 - v2);
1012 output[dst + 5][channel] = Self::float_to_short(v5 - v4);
1013 output[dst + 6][channel] = Self::float_to_short(v3 - v6);
1014 output[dst + 7][channel] = Self::float_to_short(v1 - v8);
1015 dst += 8;
1016 }
1017
1018 Ok(())
1019 }
1020
1021 fn float_to_short(f: f32) -> i16 {
1022 let a = 0x80 + ((f as i32) >> 3);
1023 if a <= 0 {
1024 0
1025 } else if a <= 0xff {
1026 a as i16
1027 } else if a < 0x180 {
1028 0xff
1029 } else {
1030 0
1031 }
1032 }
1033
1034 fn float_to_byte(f: f32) -> u8 {
1035 if f >= 255.0 {
1036 0xff
1037 } else if f <= 0.0 {
1038 0
1039 } else {
1040 f as u8
1041 }
1042 }
1043}
1044
1045struct CbgEncoder {
1046 header: BgiCBGHeader,
1047 stream: MemWriter,
1048 img: ImageData,
1049 key: u32,
1050 magic: u32,
1051}
1052
1053impl CbgEncoder {
1054 pub fn new(mut img: ImageData) -> Result<Self> {
1055 if img.depth != 8 {
1056 return Err(anyhow::anyhow!("Unsupported image depth: {}", img.depth));
1057 }
1058 let bpp = match img.color_type {
1059 ImageColorType::Bgr => 24,
1060 ImageColorType::Bgra => 32,
1061 ImageColorType::Grayscale => 8,
1062 ImageColorType::Rgb => {
1063 convert_rgb_to_bgr(&mut img)?;
1064 24
1065 }
1066 ImageColorType::Rgba => {
1067 convert_rgba_to_bgra(&mut img)?;
1068 32
1069 }
1070 };
1071 let key = rand::random();
1072 let header = BgiCBGHeader {
1073 width: img.width as u16,
1074 height: img.height as u16,
1075 bpp,
1076 _unk: 0,
1077 intermediate_length: 0,
1078 key,
1079 enc_length: 0,
1080 check_sum: 0,
1081 check_xor: 0,
1082 version: 1,
1083 };
1084
1085 Ok(CbgEncoder {
1086 header,
1087 stream: MemWriter::new(),
1088 img,
1089 key,
1090 magic: 0,
1091 })
1092 }
1093
1094 pub fn encode(mut self) -> Result<Vec<u8>> {
1095 self.stream.write_all(b"CompressedBG___\0")?;
1096 let header_pos = self.stream.pos;
1097 self.stream.seek(std::io::SeekFrom::Current(0x20))?;
1098
1099 let pixel_size = (self.header.bpp / 8) as usize;
1100 let stride = self.header.width as usize * pixel_size;
1101 let mut sampled_data = self.img.data.clone();
1102 self.average_sampling(&mut sampled_data, stride, pixel_size);
1103
1104 let packed_data = Self::pack_zeros(&sampled_data);
1105 self.header.intermediate_length = packed_data.len() as u32;
1106
1107 let mut frequencies = vec![0u32; 256];
1108 for &byte in &packed_data {
1109 frequencies[byte as usize] += 1;
1110 }
1111 if frequencies.iter().all(|&f| f == 0) {
1112 frequencies[0] = 1;
1113 }
1114
1115 let tree = HuffmanTree::new(&frequencies, false);
1116
1117 let mut weight_writer = MemWriter::new();
1118 for &weight in &frequencies {
1119 Self::write_int(&mut weight_writer, weight as i32)?;
1120 }
1121 let weight_data = weight_writer.into_inner();
1122 self.write_encoded(&weight_data)?;
1123
1124 let mut bit_writer = MsbBitWriter::new(&mut self.stream);
1125 for &byte in &packed_data {
1126 tree.encode_token(&mut bit_writer, byte as usize)?;
1127 }
1128 bit_writer.flush()?;
1129
1130 let final_pos = self.stream.pos;
1131 self.stream.pos = header_pos;
1132 self.header.pack(&mut self.stream, false, Encoding::Cp932)?;
1133 self.stream.pos = final_pos;
1134
1135 Ok(self.stream.into_inner())
1136 }
1137
1138 fn average_sampling(&self, data: &mut [u8], stride: usize, pixel_size: usize) {
1139 for y in (0..self.header.height as usize).rev() {
1140 let line = y * stride;
1141 for x in (0..self.header.width as usize).rev() {
1142 let pixel = line + x * pixel_size;
1143 for p in 0..pixel_size {
1144 let mut avg = 0u32;
1145 let mut count = 0;
1146 if x > 0 {
1147 avg = avg.wrapping_add(data[pixel + p - pixel_size] as u32);
1148 count += 1;
1149 }
1150 if y > 0 {
1151 avg = avg.wrapping_add(data[pixel + p - stride] as u32);
1152 count += 1;
1153 }
1154 if count > 0 {
1155 avg /= count;
1156 }
1157 if avg != 0 {
1158 data[pixel + p] = data[pixel + p].wrapping_sub(avg as u8);
1159 }
1160 }
1161 }
1162 }
1163 }
1164
1165 fn pack_zeros(input: &[u8]) -> Vec<u8> {
1166 let mut output = Vec::new();
1167 let mut i = 0;
1168 let mut is_zero_run = false;
1169
1170 while i < input.len() {
1171 let mut count = 0;
1172 if is_zero_run {
1173 while i + count < input.len() && input[i + count] == 0 {
1174 count += 1;
1175 }
1176 } else {
1177 while i + count < input.len() && input[i + count] != 0 {
1178 count += 1;
1179 }
1180 }
1181
1182 let mut count_buf = Vec::new();
1183 let mut n = count;
1184 loop {
1185 let mut byte = (n & 0x7f) as u8;
1186 n >>= 7;
1187 if n > 0 {
1188 byte |= 0x80;
1189 }
1190 count_buf.push(byte);
1191 if n == 0 {
1192 break;
1193 }
1194 }
1195 output.extend_from_slice(&count_buf);
1196
1197 if !is_zero_run {
1198 output.extend_from_slice(&input[i..i + count]);
1199 }
1200 i += count;
1201 is_zero_run = !is_zero_run;
1202 }
1203 output
1204 }
1205
1206 fn write_int<W: Write>(writer: &mut W, mut value: i32) -> Result<()> {
1207 loop {
1208 let mut b = (value as u8) & 0x7f;
1209 value >>= 7;
1210 if value != 0 {
1211 b |= 0x80;
1212 }
1213 writer.write_u8(b)?;
1214 if value == 0 {
1215 break;
1216 }
1217 }
1218 Ok(())
1219 }
1220
1221 fn write_encoded(&mut self, data: &[u8]) -> Result<()> {
1222 self.header.enc_length = data.len() as u32;
1223 let mut sum = 0u8;
1224 let mut xor = 0u8;
1225 let mut encoded_data = Vec::with_capacity(data.len());
1226 for &byte in data {
1227 let encrypted_byte = byte.wrapping_add(self.update_key());
1228 sum = sum.wrapping_add(byte);
1229 xor ^= byte;
1230 encoded_data.push(encrypted_byte);
1231 }
1232 self.header.check_sum = sum;
1233 self.header.check_xor = xor;
1234 self.stream.write_all(&encoded_data)?;
1235 Ok(())
1236 }
1237
1238 fn update_key(&mut self) -> u8 {
1239 let v0 = 20021 * (self.key & 0xffff);
1240 let mut v1 = self.magic | (self.key >> 16);
1241 v1 = v1
1242 .overflowing_mul(20021)
1243 .0
1244 .overflowing_add(self.key.overflowing_mul(346).0)
1245 .0;
1246 v1 = (v1 + (v0 >> 16)) & 0xffff;
1247 self.key = (v1 << 16) + (v0 & 0xffff) + 1;
1248 v1 as u8
1249 }
1250}